package com.william.jdbcplus.core.interceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * JDK 拦截器代理类
 *
 * @author william
 */
public class JdkProxyHandler implements InvocationHandler {

    private Object target = null;
    private List<Interceptor> interceptors = new ArrayList<>();

    public JdkProxyHandler(Object target, List<Interceptor> interceptors) {
        this.target = target;
        this.interceptors = interceptors;
    }

    public static Object bind(Object target, Interceptor... interceptors) {
        List<Interceptor> interceptorList = Arrays.asList(interceptors);
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new JdkProxyHandler(target, interceptorList));
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (interceptors == null || interceptors.size() == 0) {
            return method.invoke(target, args);
        }
        Object returnObj = null;
        boolean isAllBefore = true;
        Interceptor interceptorAround = null;
        for (Interceptor interceptor : interceptors) {
            if (interceptor.before(proxy, target, method, args)) {
            } else {
                isAllBefore = false;
                interceptorAround = interceptor;
            }
        }

        if (isAllBefore) {
            returnObj = method.invoke(target, args);
        } else {
            interceptorAround.around(proxy, target, method, args);
        }

        for (int i = 0; i < interceptors.size(); i++) {
            Interceptor interceptor = interceptors.get(interceptors.size() - 1 - i);
            interceptor.after(proxy, target, method, args);
        }

        return returnObj;
    }
}
